package com.example.interceptor;

import com.mybatis.pagesort.MyPageSortHelper;
import com.mybatis.util.ClassUtil;
import com.mybatis.util.SqlUtil;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;

import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
@Intercepts(@Signature(type = Executor.class,method = "query",args = {MappedStatement.class,Object.class,
        RowBounds.class, ResultHandler.class}))
public class MyPageInterceptor implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        //就考虑数据源是mysql情况
        final Object[] queryArgs = invocation.getArgs();
        final Object parameter = queryArgs[1];
        Pageable pageable = ClassUtil.findObjectFromParams(parameter, Pageable.class);
        Sort sort = ClassUtil.findObjectFromParams(parameter, Sort.class);
        if (pageable==null&&sort==null)
        {
            return invocation.proceed();
        }
        final  MappedStatement ms = (MappedStatement) queryArgs[0];
        final BoundSql boundSql = ms.getBoundSql(parameter);
        //将获得的sql后面的;去掉，应该没有吧，除非是通过注解写的时候，自己加的
        String sql = MyPageSortHelper.removeSqlSemicolon(boundSql.getSql().trim());
        if (pageable==null)
        {
            String orderSql = SqlUtil.applySorting(sql,sort);
            queryArgs[0] = MyPageSortHelper.copyFromNewSql(ms,boundSql,orderSql);
            return invocation.proceed();
        }
        else {
            //这边还判断了是否是simplepagerequest，是否分页等，此处不考虑
            int total = MyPageSortHelper.queryTotal(sql, ms, boundSql);;
            // 参数sort优先于pageable中的sort
            if (sort == null && pageable.getSort() != null) {
                sort = pageable.getSort();
            }

            if (sort != null) {
                sql = SqlUtil.applySorting(sql, sort);
            }
            String pageSql = MyPageSortHelper.getPageSql(sql, pageable.getOffset(), pageable.getPageSize());
            //获得了pagesql后，替换boundsql和mappedstatement，然后获得返回值，用page对象包装，return
            queryArgs[2] = new RowBounds(RowBounds.NO_ROW_OFFSET,RowBounds.NO_ROW_LIMIT);
            queryArgs[0] = MyPageSortHelper.copyFromNewSql(ms,boundSql,pageSql);
            Object ret = null;
            if (total==0)
            {
                ret = new ArrayList<>();
            }
            else {
                ret = invocation.proceed();
            }
            Page<?> page = new PageImpl((List<Object>)ret,pageable,total);
            List<Page<?>> result = new ArrayList<>(1);
            result.add(page);
            //终于他么抄完了
            return result;
        }

    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target,this);
    }

    @Override
    public void setProperties(Properties properties) {
        //合并属性用，不知道需不需要
    }
}
